#include <cairo.h>
#include <gtk/gtk.h>
#include <math.h>
#include <stdlib.h>

cairo_surface_t *image;

static gboolean on_expose_event(GtkWidget *widget, GdkEventExpose *event,
		gpointer data) {
	cairo_t *cr;

	static gint pos_x = 128;
	static gint pos_y = 128;
	gint radius = 40;
	/* 记录X,Y轴的移动速度 */
	static gint delta[] = { 3, 3 };

	cr = gdk_cairo_create(widget->window);

	gint width, height;
	gtk_window_get_size(GTK_WINDOW(widget), &width, &height);

	/* 当这个圆形区域碰到窗口边界，它的移动方向就会随机改变 */
	if (pos_x < 0 + radius) {
		delta[0] = rand() % 4 + 5;
	} else if (pos_x > width - radius) {
		delta[0] = -(rand() % 4 + 5);
	}

	if (pos_y < 0 + radius) {
		delta[1] = rand() % 4 + 5;
	} else if (pos_y > height - radius) {
		delta[1] = -(rand() % 4 + 5);
	}

	pos_x += delta[0];
	pos_y += delta[1];
	/*这里是绘制一幅图像和一个圆。注意：这时，图形尚未绘制到窗口中，它们还在内存里*/
	cairo_set_source_surface(cr, image, 1, 1);
	cairo_arc(cr, pos_x, pos_y, radius, 0, 2 * M_PI);
	/*cairo_clip() 函数设定裁剪域——当前所用的路径，即 cairo_arc() 函数所创建的路径*/
	cairo_clip(cr);
	/* 绘制当前落入裁剪域中的源 */
	cairo_paint(cr);
	/* 释放资源 */
	cairo_destroy(cr);
	return FALSE;
}

static gboolean time_handler(GtkWidget *widget) {
	if (widget->window == NULL)
		return FALSE;
	/* 定时调用绘制请求 */
	gtk_widget_queue_draw(widget);
	return TRUE;
}

int main(int argc, char *argv[]) {
	GtkWidget *window;
	gint width, height;

	/* 从png图片创建一个cairo_surface_t */
	image = cairo_image_surface_create_from_png("../assert/turnacastle.png");
	width = cairo_image_surface_get_width(image);
	height = cairo_image_surface_get_height(image);

	gtk_init(&argc, &argv);

	window = gtk_window_new(GTK_WINDOW_TOPLEVEL);

	g_signal_connect(G_OBJECT(window), "expose-event",
			G_CALLBACK(on_expose_event), NULL);
	g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit),
			NULL);

	gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
	gtk_window_set_default_size(GTK_WINDOW(window), width + 2, height + 2);

	gtk_widget_set_app_paintable(window, TRUE);
	gtk_widget_show_all(window);
	/* 每15ms调用一次这个time_handler函数 */
	g_timeout_add(10, (GSourceFunc) time_handler, (gpointer) window);

	gtk_main();

	cairo_surface_destroy(image);

	return 0;
}
